Skip to content

test: add CFN synthesis tests covering 24 plugin scenarios#704

Open
sid88in wants to merge 2 commits into
masterfrom
chore/cfn-synthesis-tests
Open

test: add CFN synthesis tests covering 24 plugin scenarios#704
sid88in wants to merge 2 commits into
masterfrom
chore/cfn-synthesis-tests

Conversation

@sid88in
Copy link
Copy Markdown
Owner

@sid88in sid88in commented May 24, 2026

test: add CFN synthesis tests covering 24 plugin scenarios

What

Adds a second-tier test suite that exercises the plugin against real
serverless.yml configurations and asserts on the generated
CloudFormation, complementing the existing 287 unit tests. Includes 24
runnable example projects under examples/ that double as user-facing
documentation.

Why

Unit tests catch logic and validation bugs but can't tell you whether
the plugin actually produces working CloudFormation across the matrix
of features users combine in practice. This adds that layer without
requiring AWS credentials or real deployments — sls package does the
synthesis locally and we assert on the template.

Side benefit: the project had no examples/ folder. Users had to read
the test fixtures or piece together docs to learn how to configure a
feature. These examples are copy-paste-ready and guaranteed to stay
current with the plugin's actual behavior — if they break, CI fails.

Coverage

24 fixtures, 68 assertions:

Auth (6): basic-api-key, cognito-userpools, iam-auth, oidc-auth,
lambda-authorizer, multi-auth

Resolvers (3): lambda-resolvers-js (JS code with @aws-appsync/utils),
lambda-resolvers-vtl (VTL templates), pipeline-resolvers

Data sources (6): datasource-http (with both unauthenticated and
IAM-signed variants), datasource-none, datasource-eventbridge,
datasource-opensearch, datasource-rds, plus DynamoDB and Lambda
covered transitively through other fixtures

Advanced features (9): caching (API + per-resolver),
waf (rules + association), logging-xray, custom-domain
(CloudFormation-managed), introspection-disabled
(with queryDepthLimit and resolverCountLimit), substitutions,
environment-variables, api-keys-multiple, tags,
visibility-private, schema-multiple-files

Infrastructure

  • e2e/helpers/synthesize.ts — runs sls package via a child process,
    returns the parsed CFN template, cleans up temp dirs
  • e2e/helpers/assertions.ts — readable assertion helpers
    (expectAuthenticationType, expectDataSourceOfType,
    expectResourceWithProperties, etc.)
  • jest.e2e.config.ts + jest.e2e.setup.ts — separate Jest config
    (so unit-test feedback stays fast); globalSetup creates the
    examples/node_modules/serverless-appsync-plugin symlink so example
    projects resolve the plugin from the current source tree, without
    needing a per-example npm install
  • examples/README.md indexes all 24 examples for users browsing the repo
  • e2e/README.md explains the testing strategy for contributors

CI

New e2e job in .github/workflows/ci.yml runs after the unit-test
matrix on every PR and push to master or alpha. Single Node version
(22) since CFN output doesn't vary by Node version — runs in ~70 seconds.

Real plugin behaviors caught while building the fixtures

These are the kind of "silent gotcha" issues the suite is meant to
surface — found and used to refine the examples themselves:

  1. API_KEY auth silently produces zero API keys if apiKeys: array
    isn't specified
  2. HTTP data sources with AWS_IAM authorization require explicit
    iamRoleStatements
  3. OpenSearch data sources can't auto-derive the ARN from Fn::GetAtt
    — they need an explicit domain: field naming the CloudFormation
    resource

How to run locally

# Unit tests (unchanged)
npm run test

# CFN synthesis tests
npm run test:e2e

# Everything
npm run test:all

# Single fixture
npx jest --config jest.e2e.config.ts basic-api-key

Verified

  • npm run test — 287 unit tests pass
  • npm run test:e2e — 68 synthesis assertions across 25 suites pass
  • npm run lint — clean (0 errors, 0 warnings)
  • npm run build — clean
  • ✅ Full suite runs in ~80 seconds locally

What's not in this PR (intentionally)

  • No real-AWS deploy tests (Tier 2) — separate follow-up work that
    needs a dedicated AWS test account and OIDC setup
  • No merged-api example — the plugin doesn't support MERGED API
    type yet; that's a roadmap item, not a missed test

Follow-ups for after merge

  • Real-AWS Tier 2 tests for end-to-end deployment verification on a
    scheduled cadence
  • Continue expanding fixtures as new features land (e.g. AppSync Events
    API once supported, MERGED APIs once supported)
  • Consider linking from the main README to the examples/ folder

Adds a second-tier test suite that exercises the plugin against real
serverless.yml configurations and asserts on the generated CloudFormation
template, complementing the existing 287 unit tests.

Coverage (24 fixtures, 68 assertions):

Auth (6): basic-api-key, cognito-userpools, iam-auth, oidc-auth,
  lambda-authorizer, multi-auth

Resolvers (3): lambda-resolvers-js (JS code + esbuild bundling),
  lambda-resolvers-vtl (VTL templates), pipeline-resolvers

Data sources (6): datasource-http (incl. IAM-signed variant),
  datasource-none, datasource-eventbridge, datasource-opensearch,
  datasource-rds, plus DynamoDB and Lambda covered transitively

Advanced features (9): caching (API + per-resolver), waf (rules,
  associations), logging-xray, custom-domain (CloudFormation-managed),
  introspection-disabled (with queryDepth/resolverCount limits),
  substitutions, environment-variables, api-keys-multiple,
  tags, visibility-private, schema-multiple-files

Infrastructure:
- e2e/helpers/synthesize.ts — runs sls package via subprocess, returns
  parsed CFN template, cleans up temp dirs
- e2e/helpers/assertions.ts — readable assertion helpers
  (expectAuthenticationType, expectDataSourceOfType, etc.)
- jest.e2e.config.ts + jest.e2e.setup.ts — separate config; globalSetup
  creates the examples/node_modules/serverless-appsync-plugin symlink
  so example projects resolve the plugin from the current source tree
- Each example is a copy-paste-ready user project doubling as a test
  fixture, eliminating the docs/tests duplication problem
- examples/README.md indexes all 24 examples for users
- e2e/README.md explains the testing strategy for contributors

CI: new 'e2e' job in .github/workflows/ci.yml runs after the unit-test
matrix on every PR and push to master/alpha. Single Node version (22)
since CFN output doesn't vary by Node version; full suite takes ~70s.

Real plugin behaviors caught while building the fixtures (used to refine
the examples):
- API_KEY auth silently produces zero API keys if 'apiKeys:' is omitted
- HTTP data sources with AWS_IAM authorization require explicit
  iamRoleStatements
- OpenSearch data source can't auto-derive ARN from Fn::GetAtt; needs
  'domain:' field naming the CloudFormation resource

Verified: npm run test:all passes (287 unit + 68 e2e), npm run lint
clean.
@sid88in sid88in requested a review from AlexHladin May 24, 2026 20:54
Comment thread .github/workflows/ci.yml Outdated
needs: tests
steps:
- name: Checkout code
uses: actions/checkout@v5
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sid88in let's switch to the latest v6 version

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! bumped

Comment thread .github/workflows/ci.yml Outdated
steps:
- name: Checkout code
uses: actions/checkout@v5
- uses: actions/setup-node@v5
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sid88in this one, also could be switched to v6

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! bumped

Comment thread .github/workflows/ci.yml
uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sid88in the plugin supports 20, 22, 24, and 26 versions, just curious why 22?

Copy link
Copy Markdown
Owner Author

@sid88in sid88in May 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CFN output is identical across Node versions. Running 4 Node versions for the synthesis tests would be 4x the CI minutes for zero added signal. The unit-test matrix already verifies the plugin works across Node 20/22/24/26 — those tests exercise the actual plugin logic. The e2e job tests the output of that logic, which doesn't change based on Node.
That said, 22 is somewhat arbitrary — could have been any of the four. For now I will keep it 22

Comment thread e2e/helpers/assertions.ts Outdated
Comment on lines +100 to +104
| 'API_KEY'
| 'AWS_IAM'
| 'AMAZON_COGNITO_USER_POOLS'
| 'OPENID_CONNECT'
| 'AWS_LAMBDA',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sid88in, how about export this type from here, and use here?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch fixed


provider:
name: aws
runtime: nodejs20.x
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sid88in nodejs20 is not supported by AWS, only 22 and 24

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch node 20x is EOL April 30, moved to 22

- Bump actions/checkout and actions/setup-node to v6 (latest stable)
  in both the tests and e2e jobs of .github/workflows/ci.yml
- Bump all example runtimes from nodejs20.x to nodejs22.x. Node 20
  reached EOL on April 30 2026; Lambda console removed it then and
  function updates will be blocked from Sep 30 2026. Examples should
  reflect the current recommended runtime so users copying them get a
  supported runtime by default.
- Export AuthenticationType union from src/types/common.ts (derived
  from the existing Auth discriminated union via Auth['type']) and
  use it in e2e/helpers/assertions.ts instead of duplicating the
  literal string union. Keeps the e2e helper and the source of truth
  in sync automatically if a new auth type is ever added.

Re: 'why Node 22 for the e2e job and not the full 20/22/24/26 matrix?'
The CFN output produced by serverless package is identical across Node
versions (no Node-specific code paths in synthesis). The existing
unit-test matrix already verifies plugin logic across all four Node
versions; running the synthesis tests across the same matrix would 4x
CI minutes for zero added signal. 22 specifically matches what the
Release workflow uses, keeping CI consistent.
@sid88in
Copy link
Copy Markdown
Owner Author

sid88in commented May 26, 2026

@AlexHladin please review the CR again. addressed comments - pls verify

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants